const { resolve } = require('path')
const HtmlWebpackPlugin = require('html-webpack-plugin')

const MiniCssExtractPlugin = require('mini-css-extract-plugin')
const optimizeCssAssetsWebpackPlugin = require('optimize-css-assets-webpack-plugin')

// 复用loader
const commonCssLoader = [
  MiniCssExtractPlugin.loader,
  'css-loader',
  {
    loader: 'postcss-loader',
    options: {
      ident: 'postcss',
      plugins: () => [require('postcss-preset-env')()]
    }
  }
]


/**
 * 缓存：
 *  babel缓存
 *    cacheDirectory: true
 *    --> 让第二次打包构建速度更快
 *  文件资源缓存
 *    hash: 每次webpack构建时会生成一个唯一的hash值【不管文件是否变化都会变化】
 *    维护hash值得变化控制资源得是否更新
 *      问题：因为js和css同时使用一个hash值，
 *            如果重新打包，会导致所有缓存失效。（可能我只改动一个文件）
 *    引入chunkhash值 ： 根据chunk生成的hash值，如果打包来源于同一个chunk，那么hash值就生效
 *      问题：js和css的hash值还是一样的
 *        因为css是在js中被引入的，同属于一个chunk
 *    contenthash: 根据文件的内容生成hash值，不同文件的hash值一定不一样
 *    --> 让代码上线运行缓存更好使用
 */

module.exports = {
  entry: './src/js/index.js',
  output: {
    // 增加构建目录的hash值，防止服务器强缓存
    filename: 'js/built.[contenthash:10].js',
    path: resolve(__dirname, 'build')
  },
  module: {
    rules: [
      /**
       * 正常来讲，一个文件只能被一个loader处理
       * 当一个文件要被多个loader处理时，一定要指定loader的执行先后顺序
       * 先执行eslint后执行babel
       */
      {
        test: /\.js$/,
        exclude: /node_modules/,
        loader: 'eslint-loader',
        // 让eslint优先执行
        enforce: 'pre',
        options: {
          fix: true
        }
      },
      {
        /**
         * oneOf: 提升构建速度，防止文件被多个loader处理
         * 一下loader只会匹配一个，提升loader的处理性能，命中即不再匹配
         * 注意：不能有两个配置处理同一个类型文件（如babel和eslint都处理js文件，需要把eslint提取出去，放到数组内）
         */
        oneOf: [
          {
            test: /\.css$/,
            use: [...commonCssLoader]
          },
          {
            test: /\.less$/,
            use: [...commonCssLoader, 'less-loader']
          },

          {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            options: {
              presets: [
                [
                  '@babel/preset-env',
                  {
                    useBuiltIns: 'usage',
                    corejs: {
                      version: 3
                    },
                    targets: {
                      chrome: '60',
                      firefox: '60',
                      ie: '9',
                      safari: '10',
                      edge: '17'
                    }
                  }
                ]
              ],
              // 开启babel缓存
              // 第二次构建时，会读取之前的缓存
              cacheDirectory: true
            }
          },
          {
            test: /\.(png|jpg|gif)$/,
            use: [
              {
                loader: 'url-loader', // url-loader 依赖file-loader,是对file-loader的一些优化（压缩图片）
                options: {
                  limit: 8196,
                  name: 'img/[name].[hash:8].[ext]',
                  esModule: false,
                  outputPath: 'imgs' // 打包到imgs目录下
                }
              }
            ]
          },
          {
            test: /\.html$/,
            loader: 'html-loader'
          },
          {
            exclude: /\.(css|js|html|less|jpg|png|gif)$/,
            loader: 'file-loader',
            options: {
              outputPath: 'media',
              name: '[hash: 10].[ext]'
            }
          }
        ]
      }
    ]
  },
  plugins: [
    new HtmlWebpackPlugin({
      template: './src/index.html',
      minify: {
        collapseWhitespace: true,
        removeComments: true
      }
    }),
    new MiniCssExtractPlugin({
      filename: 'css/main.[contenthash:10].css'
    }),
    new optimizeCssAssetsWebpackPlugin()
  ],
  mode: 'production',
  devtool: 'source-map'
}
